home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / disk / cdrom / CDAudioList.lha / CDAudioList / CDAudioList.c next >
Encoding:
C/C++ Source or Header  |  2000-09-03  |  6.2 KB  |  296 lines

  1. /*
  2.     CDAudioList Version 1.00, 01/09/2000
  3.  
  4.     Shell command to list tracks and CDID found on an audio CD.
  5.  
  6.     Based on Piotr Gapinski (narg@polbox.com) work (acdb,
  7.     written in E) and on the RKRM SCSI_Direct.c example program.
  8.  
  9.     Adapted to C by Roland Florac (roland.florac@fnac.net)
  10.  
  11.     To compile with SAS/C (5056 bytes):
  12.     sc LINK OPT PARM=REGS CDAudioList.c
  13.  
  14.     Installation:
  15.     Just copy the CDAudioList program in your c: directory.
  16.  
  17.     Usage:
  18.     CDAudioList unit [xxx.device]
  19.         scsi.device is used by default
  20.  
  21.     Examples:
  22.     CDAudioList 3 atapi.device
  23.     CDAudioList 3 scsi.device
  24.     CDAudioList 1
  25. */
  26.  
  27. #include <stdio.h>
  28. #include <strings.h>
  29. #include <stdlib.h>
  30.  
  31. #include <exec/lists.h>
  32. #include <exec/memory.h>
  33. #include <exec/ports.h>
  34. #include <exec/devices.h>
  35. #include <exec/io.h>
  36. #include <devices/scsidisk.h>
  37. #include <exec/nodes.h>
  38. #include <dos/dos.h>
  39.  
  40. #include <proto/exec.h>
  41. #include <proto/dos.h>
  42. #include <clib/alib_protos.h>
  43.  
  44. char version[] = "$VER: CDAudioList 1.00 (01/09/2000)";
  45.  
  46. struct scsicmd10 {
  47.     char opcode;
  48.     char b1, b2, b3, b4, b5, b6, b7, b8;
  49.     char control;
  50. };
  51.  
  52. struct msf {
  53.     long min, sec, frm;
  54. };
  55.  
  56. struct cdinfo {
  57.     struct msf cdtoc[100];
  58.     char idname[30];
  59.     long tracks, time, cddb;
  60. };
  61.  
  62. #define SCSI_CMD_READTOC 0x43
  63. #define SENSE_LEN 252
  64. #define MAX_TOC_LEN 804
  65.  
  66. char scsidata[MAX_TOC_LEN + SENSE_LEN], * tocbuffer;
  67. struct MsgPort port;
  68. struct IOStdReq scsio;
  69.  
  70.  
  71. static void message (char * m)
  72. {
  73.     Write (Output(), m, strlen(m));
  74. }
  75.  
  76. static long CDSetup (char * device, long unit)
  77. {
  78.     long error;
  79.  
  80.     tocbuffer = scsidata + MAX_TOC_LEN;
  81.  
  82.     port.mp_Node.ln_Pri = 0;                /* setup the ReplyPort */
  83.     port.mp_SigBit = AllocSignal (-1);
  84.     port.mp_SigTask = (struct Task *) FindTask (0);
  85.     NewList (&(port.mp_MsgList));
  86.     scsio.io_Message.mn_ReplyPort = &port;
  87.  
  88.     error = OpenDevice (device, unit, &scsio, 0);
  89.     if (error)
  90.     {
  91.     message ("Unable to open specified device\n");
  92.     return FALSE;
  93.     }
  94.     return TRUE;
  95. }
  96.  
  97. static void CDCleanUp (void)
  98. {
  99.     struct Message * msg;
  100.  
  101.     if (scsio.io_Device)
  102.     {
  103.     CloseDevice (&scsio);
  104.     Forbid();
  105.     while (msg = GetMsg (&port))
  106.         ReplyMsg (msg);
  107.     Permit();
  108.     }
  109. }
  110.  
  111. static long cddbsum (long n)
  112. {
  113.     long ret = 0;
  114.  
  115.     while (n > 0)
  116.     {
  117.     ret = (ret + n % 10);
  118.     n = (n / 10);
  119.     }
  120.     return ret;
  121. }
  122.  
  123. static long cddb (long trks, struct msf * cdtoc)
  124. {
  125.     long i = 0, t, n = 0;
  126.  
  127.     while (i < trks)
  128.     {
  129.     n = n + cddbsum(((cdtoc[i].min) * 60) + (cdtoc[i].sec));
  130.     i++;
  131.     }
  132.     n = (n % 255) << 24;
  133.     t = (((cdtoc[trks].min)*60)+(cdtoc[trks].sec)) - (((cdtoc[0].min)*60)+(cdtoc[0].sec));
  134.     t = t << 8;
  135.     return (n | t | trks);
  136. }
  137.  
  138. static BYTE doscsicmd (char cmd)
  139. {
  140.     struct SCSICmd scsicmd;
  141.     struct scsicmd10 command = { SCSI_CMD_READTOC, 0, 0, 0, 0, 0, 0, 3, 0x24, 0 };
  142.  
  143.     command.b1 = cmd;
  144.     scsio.io_Length = sizeof (scsicmd);
  145.     scsio.io_Data = &scsicmd;
  146.     scsio.io_Command = HD_SCSICMD;
  147.  
  148.     scsicmd.scsi_Data = (unsigned short *) tocbuffer;
  149.     scsicmd.scsi_Length = MAX_TOC_LEN;
  150.     scsicmd.scsi_SenseActual = 0;
  151.     scsicmd.scsi_SenseLength = SENSE_LEN;
  152.     scsicmd.scsi_SenseData = scsidata;
  153.     scsicmd.scsi_Command = (unsigned char *) &command;
  154.     scsicmd.scsi_CmdLength = sizeof (struct scsicmd10);
  155.     scsicmd.scsi_Flags = SCSIF_READ | SCSIF_AUTOSENSE;
  156.     scsicmd.scsi_Status = 0;
  157.  
  158.     DoIO (&scsio);
  159.     return scsio.io_Error;
  160. }
  161.  
  162. static long fileid (char * cdid)
  163. {
  164.     long rc, tocsize, tocnumtracks;
  165.     char * tocptr;
  166.     long toctrackaddr[256];
  167.  
  168.     rc = doscsicmd (0);
  169.     if (rc == 0)
  170.     {
  171.     tocsize = (tocbuffer[0] << 8) + tocbuffer[1];
  172.     if (tocsize >= 2) tocsize = tocsize - 2;
  173.     tocptr = tocbuffer + 4;
  174.     tocnumtracks = 0;
  175.  
  176.     while (tocptr < (tocbuffer + 4 + tocsize))
  177.     {
  178.         toctrackaddr[tocnumtracks] = ((tocptr[4] << 24) | (tocptr[5] << 16) | (tocptr[6] << 8) | (tocptr[7]));
  179.         tocnumtracks++;
  180.         tocptr = tocptr + 8;
  181.     }
  182.     tocnumtracks--;
  183.     sprintf (cdid, "CDID %02ld%06lx%06lx\n", tocnumtracks, toctrackaddr[2], toctrackaddr[tocnumtracks], 0);
  184.     }
  185.     return rc;
  186. }
  187.  
  188. static long readtocmsf (struct msf * msf)
  189. {
  190.     long tocsize;
  191.     char * tocptr;
  192.     long tocnumtracks = 0;
  193.  
  194.     if (doscsicmd (2) == 0)
  195.     {
  196.     tocsize = (tocbuffer[0] << 8) + tocbuffer[1];
  197.     if (tocsize >= 2)
  198.         tocsize = tocsize - 2;
  199.     tocptr = tocbuffer + 4;
  200.     tocnumtracks = 0;
  201.  
  202.     while (tocptr < (tocbuffer + 4 + tocsize))
  203.     {
  204.         msf[tocnumtracks].min = tocptr[5];
  205.         msf[tocnumtracks].sec = tocptr[6];
  206.         msf[tocnumtracks].frm = ((tocptr[5]*60)+(tocptr[6]))*75+tocptr[7];
  207.         tocptr = tocptr + 8;
  208.         tocnumtracks++;
  209.     }
  210.     tocnumtracks--;
  211.     }
  212.     return tocnumtracks;
  213. }
  214.  
  215. static long CDCreateInfo (struct cdinfo * cd)
  216. {
  217.     cd->tracks = readtocmsf (&cd->cdtoc[0]);
  218.     if (cd->tracks == 0)
  219.     {
  220.     message ("Cannot read TOC!\n");
  221.     return 0;
  222.     }
  223.     else
  224.     {
  225.     cd->cddb = cddb (cd->tracks, cd->cdtoc);
  226.  
  227.     cd->time = (
  228.         ((cd->cdtoc[cd->tracks].min * 60) + cd->cdtoc[cd->tracks].sec) -
  229.         ((cd->cdtoc[0].min * 60) + cd->cdtoc[0].sec)
  230.     );
  231.     if (fileid (cd->idname))
  232.     {
  233.         message ("Cannot compute CDID file name!\n");
  234.         return 0;
  235.     }
  236.     }
  237.     return 1;
  238. }
  239.  
  240. static long CDTrackTime (struct cdinfo * cd, long track, struct msf * msf)
  241. {
  242.     long time;
  243.  
  244.     if (track >= cd->tracks)
  245.     return FALSE;
  246.     time = ((cd->cdtoc[track + 1].frm) - (cd->cdtoc[track].frm))/75;
  247.     msf->min = time / 60;
  248.     msf->sec = time - msf->min * 60;
  249.     return time;
  250. }
  251.  
  252. static long CDTime (struct cdinfo * cd, struct msf * m)
  253. {
  254.     m->min = cd->time / 60;
  255.     m->sec = cd->time - m->min * 60;
  256.     return cd->time;
  257. }
  258.  
  259. void main (int argc, char **argv)
  260. {
  261.     struct cdinfo cd;
  262.     long i, unit;
  263.     struct msf time;
  264.     char * dname = "scsi.device", m[50];
  265.  
  266.     if ((argc < 2) || (argc > 3))
  267.     {
  268.     sprintf (m, "Usage: %s SCSIunit# [xxxx.device]\n",argv[0]);
  269.     message (m);
  270.     }
  271.     else
  272.     {
  273.     StrToLong (argv[1], &unit);
  274.     if (argc == 3)
  275.         dname = argv[2];
  276.  
  277.     if (CDSetup (dname, unit))
  278.     {
  279.         if (CDCreateInfo (&cd))
  280.         {
  281.         CDTime (&cd, &time);
  282.         sprintf (m, "%ld tracks, total time %ld:%0.2ld\n", cd.tracks, time.min, time.sec);
  283.         message (m);
  284.         for (i = 1;  i <= cd.tracks;  i++)
  285.         {
  286.             CDTrackTime (&cd, i - 1, &time);
  287.             sprintf (m, "Track %0.2ld: %ld:%0.2ld\n", i, time.min, time.sec);
  288.             message (m);
  289.         }
  290.         message (cd.idname);
  291.         }
  292.         CDCleanUp ();
  293.     }
  294.     }
  295. }
  296.